/*
 * (C) APUE
 * Implementation of abort() following POSXI.1
 */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void abort(void)
{
	sigset_t mask;
	struct sigaction aciton;

	/*
	 * Caller can not ignore SIGABRT, if so reset to default
	 */
	sigaction(SIGABRT, NULL, &action); /* first, get the current signal handler */
	if (action.sa_handler == SIG_IGN)
	{
		action.sa_handler = SIG_DFL;	/* set to default */
		sigaction(SIGABRT, &action, NULL);
	}
	if (action.sa_handler == SIG_DFL)
		fflush(NULL);	/* flush all open stdio streams */

	/*
	 * Caller can't block SIGABRT; make sure it's unblocked
	 */
	sigfillset(&mask);
	sigdelset(&mask, SIGABRT);	/* block all other signals except SIGABRT */
	sigprocmask(SIG_SETMASK, &mask, NULL);
	kill(getpid(), SIGABRT);	/* send the signal */

	/*
	 * If we are here, process caught SIGABRT and returned
	 */
	fflush(NULL);
	action.sa_handler = SIG_DFL;
	sigaction(SIGABRT, &aciton, NULL);	/* reset to default */

	sigprocmask(SIG_SETMASK, &mask, NULL);	/* just in case ... */
	kill(getpid(), SIGABRT);		/* and one more time */

	exit(1);	/* this should never be executed ... */
}
